package yang_exp.concurrent;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProductorAndConsumer2 {
    
    static class MyResource {
        Queue<Integer> productions;
        AtomicInteger ai;
        int capacity;
        private Lock lock = new ReentrantLock();
        private Condition full = lock.newCondition();
        private Condition empty = lock.newCondition();
        

        public MyResource(Queue<Integer> productions, int capacity) {
            ai = new AtomicInteger(0);
            this.productions = productions;
            this.capacity = capacity;
        }

        public void product() {
            lock.lock();
            try {
                while (this.productions.size() >= capacity) {
                    // System.out.println(Thread.currentThread().getName() +  "无空位，无法生产");
                    empty.await();
                }
                int e = ai.incrementAndGet();
                System.out.println(Thread.currentThread().getName() +  "生产了" + e);
                productions.offer(e);      
                System.out.println();         
                TimeUnit.SECONDS.sleep(1);
                full.signalAll();
            } catch (Exception e) {
            } finally {
                lock.unlock();
            }
        }

        public void consume() {
            lock.lock();
            try {
                while (this.productions.isEmpty()) {
                    // System.out.println(Thread.currentThread().getName() +  "无资源，无法消费");
                    full.await();
                }
                int e = productions.poll();
                System.out.println(Thread.currentThread().getName() +  "消费了" + e);    
                System.out.println();         
                TimeUnit.SECONDS.sleep(1);
                empty.signalAll();
            } catch (Exception e) {
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        MyResource mr = new MyResource(new LinkedList<>(), 5);

        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                mr.product();
            }, "productor" + i).start();
            new Thread(() -> {
                mr.consume();
            }, "consumer" + i).start();

        }
    }
}
